package com.cata.mall.security.config;

import com.cata.mall.security.component.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * @作者: Tao
 * @日期: 2025/10/11
 * @时间: 11:34
 * @描述: SpringSecurity相关配置，仅用于配置SecurityFilterChain<pre>
 *     1.@EnableWebSecurity:
 *          用于启用Web安全功能
 *          自动配置Spring Security的相关组件，包括认证、授权、CSRF保护等安全机制，为应用程序提供全面的安全防护
 *     2.什么是跨域
 *          前端页面和后端API的协议、域名或端口不同时，就产生了跨域请求
 *     3.CSRF:
 *          CSRF (Cross-Site Request Forgery，跨站请求伪造) 是一种网络攻击方式，攻击者诱使用户在已认证的网站上执行非预期的操作。
 *          CSRF 攻击原理
 *              用户登录网站A并获得认证cookie
 *              用户在未退出网站A的情况下访问恶意网站B
 *              恶意网站B诱导用户向网站A发送请求
 *              由于用户仍处于登录状态，请求携带有效cookie，网站A误认为是用户本人操作
 *          禁用CSRF保护适用于：
 *              基于JWT的无状态认证系统
 *              RESTful API服务
 *              前后端完全分离的应用架构
 */
@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Autowired
    private IgnoreUrlsConfig ignoreUrlsConfig;
    @Autowired
    private RestfulAccessDeniedHandler restfulAccessDeniedHandler;
    @Autowired
    private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
    @Autowired(required = false)
    private DynamicSecurityService dynamicSecurityService;
    @Autowired(required = false)
    private DynamicSecurityFilter dynamicSecurityFilter;

    /**
     * 配置Spring Security过滤器链
     *
     * @param httpSecurity HttpSecurity对象，用于配置安全过滤器
     * @return SecurityFilterChain 安全过滤器链对象
     * @throws Exception 配置过程中可能抛出的异常<pre>
     *
     *                   基于您提供的 `filterChain` 方法，其配置逻辑如下：<pre>
     *
     *                   ## 主要配置逻辑
     *
     *                   1. **资源访问控制**
     *                      - 通过 `ignoreUrlsConfig.getUrls()` 获取白名单URL，这些路径允许无认证访问
     *                      - 允许所有 `OPTIONS` 请求（用于跨域处理）
     *                      - 其他所有请求都需要身份认证
     *
     *                   2. **安全策略设置**
     *                      - 禁用 CSRF 保护（适用于 RESTful API）
     *                      - 设置会话管理策略为 `STATELESS`（无状态），不创建 HttpSession
     *
     *                   3. **异常处理配置**
     *                      - 配置 `accessDeniedHandler` 处理权限不足异常
     *                      - 配置 `authenticationEntryPoint` 处理未认证请求
     *
     *                   4. **过滤器链配置**
     *                      - 添加 [jwtAuthenticationTokenFilter](file://D:\idea\IdeaProjects\ctmall\mall-security\src\main\java\com\cata\mall\security\config\CommonSecurityConfig.java#L45-L48) 在 `UsernamePasswordAuthenticationFilter` 之前执行
     *                      - 如果存在 [dynamicSecurityService](file://D:\idea\IdeaProjects\ctmall\mall-security\src\main\java\com\cata\mall\security\component\DynamicSecurityMetadataSource.java#L23-L24)，则添加 [dynamicSecurityFilter](file://D:\idea\IdeaProjects\ctmall\mall-security\src\main\java\com\cata\mall\security\config\CommonSecurityConfig.java#L62-L66) 在 `FilterSecurityInterceptor` 之前执行
     *
     *                   这个配置实现了基于 JWT 的无状态认证机制，支持动态权限控制和白名单路径跳过认证。
     */
    @Bean
    SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = httpSecurity
                .authorizeRequests();
        //不需要保护的资源路径允许访问
        for (String url : ignoreUrlsConfig.getUrls()) {
            registry.antMatchers(url).permitAll();
        }
        //允许跨域请求的OPTIONS请求
        registry.antMatchers(HttpMethod.OPTIONS)
                .permitAll();
        //任何请求都需要身份认证
        registry.and()
                .authorizeRequests()
                .anyRequest()
                .authenticated()
                //关闭跨站请求防护及不使用session
                .and()
                .csrf()
                .disable()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                //自定义权限拒绝处理类
                .and()
                .exceptionHandling()
                .accessDeniedHandler(restfulAccessDeniedHandler)
                .authenticationEntryPoint(restAuthenticationEntryPoint)
                //自定义权限拦截器JWT过滤器
                .and()
                .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
        //有动态权限配置时添加动态权限校验过滤器
        if (dynamicSecurityService != null) {
            registry.and().addFilterBefore(dynamicSecurityFilter, FilterSecurityInterceptor.class);
        }
        return httpSecurity.build();
    }

}
